/**
 * 游戏时间引擎
 * 管理游戏内的虚拟时间，支持加速、暂停等功能
 */

export type GameTimeSpeed = 1 | 2 | 5 | 10 | 20 | 50 | 100 | 200 | 500; // 时间加速倍数
export type GameTimeStatus = "playing" | "paused";

export interface GameTimeState {
  // 游戏内日期（虚拟日期）
  gameDate: Date;
  // 游戏时间速度（相对于现实时间的倍数）
  speed: GameTimeSpeed;
  // 游戏状态
  status: GameTimeStatus;
  // 上次更新时间（现实时间戳）
  lastUpdateRealTime: number;
  // 游戏开始时的日期
  startDate: Date;
}

export class GameTimeEngine {
  private state: GameTimeState;

  constructor(initialDate?: Date) {
    const startDate = initialDate ?? new Date("2035-01-01T09:00:00");
    this.state = {
      gameDate: new Date(startDate),
      speed: 1,
      status: "playing",
      lastUpdateRealTime: Date.now(),
      startDate: new Date(startDate),
    };
  }

  /**
   * 获取当前游戏时间状态
   */
  getState(): GameTimeState {
    this.update();
    return {
      ...this.state,
      gameDate: new Date(this.state.gameDate),
      startDate: new Date(this.state.startDate),
    };
  }

  /**
   * 获取当前游戏日期
   */
  getGameDate(): Date {
    this.update();
    return new Date(this.state.gameDate);
  }

  /**
   * 设置游戏时间速度
   */
  setSpeed(speed: GameTimeSpeed): void {
    this.update();
    this.state.speed = speed;
    this.state.lastUpdateRealTime = Date.now();
  }

  /**
   * 获取当前时间速度
   */
  getSpeed(): GameTimeSpeed {
    return this.state.speed;
  }

  /**
   * 暂停游戏时间
   */
  pause(): void {
    this.update();
    this.state.status = "paused";
    this.state.lastUpdateRealTime = Date.now();
  }

  /**
   * 继续游戏时间
   */
  resume(): void {
    this.update();
    this.state.status = "playing";
    this.state.lastUpdateRealTime = Date.now();
  }

  /**
   * 切换暂停/继续状态
   */
  toggle(): void {
    if (this.state.status === "playing") {
      this.pause();
    } else {
      this.resume();
    }
  }

  /**
   * 跳转到指定日期（仅工作日，市场开盘时间）
   */
  jumpToDate(targetDate: Date): void {
    this.update();
    this.state.gameDate = new Date(targetDate);
    this.state.lastUpdateRealTime = Date.now();
  }

  /**
   * 检查是否为交易日（简化版：周一到周五）
   */
  isTradingDay(date?: Date): boolean {
    const checkDate = date ?? this.getGameDate();
    const dayOfWeek = checkDate.getDay();
    return dayOfWeek >= 1 && dayOfWeek <= 5; // 周一到周五
  }

  /**
   * 检查是否为交易时间（简化版：9:00-15:00）
   */
  isTradingHours(date?: Date): boolean {
    const checkDate = date ?? this.getGameDate();
    if (!this.isTradingDay(checkDate)) {
      return false;
    }
    const hour = checkDate.getHours();
    return hour >= 9 && hour < 15;
  }

  /**
   * 获取距离下一次市场开盘的时间（游戏时间）
   */
  getTimeToNextMarketOpen(): number {
    this.update();
    const now = new Date(this.state.gameDate);
    const nextOpen = new Date(now);

    // 如果当前是交易时间，返回明天开盘时间
    if (this.isTradingHours(now)) {
      nextOpen.setDate(nextOpen.getDate() + 1);
    }

    // 找到下一个交易日
    while (!this.isTradingDay(nextOpen)) {
      nextOpen.setDate(nextOpen.getDate() + 1);
    }

    // 设置为9:00开盘
    nextOpen.setHours(9, 0, 0, 0);

    return nextOpen.getTime() - now.getTime();
  }

  /**
   * 跳转到下一个交易日开盘时间
   */
  skipToNextTradingDay(): void {
    this.update();
    const now = new Date(this.state.gameDate);
    const nextOpen = new Date(now);

    // 跳到第二天
    nextOpen.setDate(nextOpen.getDate() + 1);

    // 找到下一个交易日
    while (!this.isTradingDay(nextOpen)) {
      nextOpen.setDate(nextOpen.getDate() + 1);
    }

    // 设置为9:30开盘
    nextOpen.setHours(9, 30, 0, 0);

    this.state.gameDate = nextOpen;
    this.state.lastUpdateRealTime = Date.now();
  }

  /**
   * 内部更新方法：根据现实时间流逝计算游戏时间推进
   */
  private update(): void {
    if (this.state.status === "paused") {
      return;
    }

    const now = Date.now();
    const realTimeDelta = now - this.state.lastUpdateRealTime; // 现实时间流逝（毫秒）

    // 根据速度计算游戏时间流逝
    const gameTimeDelta = realTimeDelta * this.state.speed; // 游戏时间流逝（毫秒）

    // 更新游戏日期
    this.state.gameDate = new Date(
      this.state.gameDate.getTime() + gameTimeDelta,
    );
    this.state.lastUpdateRealTime = now;
  }

  /**
   * 格式化游戏日期为字符串
   */
  formatDate(date?: Date): string {
    const d = date ?? this.getGameDate();
    return d.toLocaleString("zh-CN", {
      year: "numeric",
      month: "2-digit",
      day: "2-digit",
      hour: "2-digit",
      minute: "2-digit",
      weekday: "short",
    });
  }

  /**
   * 获取游戏运行总时长（现实时间）
   */
  getRealTimeElapsed(): number {
    return Date.now() - this.state.lastUpdateRealTime;
  }

  /**
   * 获取游戏内已过时间（游戏时间）
   */
  getGameTimeElapsed(): number {
    this.update();
    return this.state.gameDate.getTime() - this.state.startDate.getTime();
  }
}

// 单例实例（全局共享）
let gameTimeInstance: GameTimeEngine | null = null;

/**
 * 获取游戏时间引擎单例
 */
export function getGameTimeEngine(initialDate?: Date): GameTimeEngine {
  if (!gameTimeInstance) {
    gameTimeInstance = new GameTimeEngine(initialDate);
  }
  return gameTimeInstance;
}

/**
 * 重置游戏时间引擎（用于测试或新游戏）
 */
export function resetGameTimeEngine(initialDate?: Date): GameTimeEngine {
  gameTimeInstance = new GameTimeEngine(initialDate);
  return gameTimeInstance;
}




